import { reactive } from "vue";
import { SFItemService } from "./sf-item/sf-item.service";
import { NzSafeAny } from "./type";

export class SFService {
  private items = reactive<Record<string, SFItemService>>({});
  private _values = {} as Record<string, NzSafeAny>;
  constructor(values: Record<string, NzSafeAny>) {
    this._values = values;
  }

  getKey(key: string, parent = "") {
    return `${parent}/${key}`;
  }

  private processNxt(obj: Record<string, NzSafeAny>, key: string) {
    const values = {} as Record<string, NzSafeAny>;
    Object.keys(obj).forEach(k => {
      const service = this.items[this.getKey(k, key)];
      if (service) {
        if (!service.params.ignore) {
          if (service.widget === "object") {
            values[k] = this.processNxt(obj[k], this.getKey(k, key));
          } else {
            values[k] = service?.nxtFormat
              ? service.nxtFormat(this._values[k])
              : obj[k];
          }
        }
      } else {
        /** 不是定义SCHema 直接赋值 */
        values[k] = obj[k];
      }
    });
    return values;
  }

  setItem(i: SFItemService, key: string) {
    this.items[key] = i;
  }

  getValues() {
    return this.processNxt(this._values, "");
  }

  setVaule(key: string, value: NzSafeAny) {
    const vals = key.split("/").filter(r => r);
    if (vals.length) {
      if (vals.length === 1) {
        this._values[vals[0]] = value;
      } else {
        let middle = this._values[vals[0]];
        vals.slice(1).forEach((v, i) => {
          if (i === vals.length - 2) {
            middle[v] = value;
          } else {
            middle = middle[v];
          }
        });
      }
    }
  }

  getVaule(key: string) {
    const vals = key.split("/").filter(r => r);
    if (vals.length) {
      if (vals.length === 1) {
        return this._values[vals[0]];
      } else {
        let middle = this._values[vals[0]];
        vals.slice(1).forEach(v => {
          middle = middle[v];
        });
        return middle;
      }
    }
  }

  getProperty<T>(key: string) {
    return this.items[key] as unknown as SFItemService<T>;
  }

  get vaild() {
    return Object.keys(this.items).every(k => {
      const validate = this.items[k].validate;
      if (!this.items[k].visible) {
        return true;
      }
      if (!this.items[k].asyncChangeValid) {
        return false;
      }

      const value = this.getVaule(k);
      const result = validate
        ? validate.every(v => {
            let ok = true;
            if (v.required && ["", null, undefined].includes(value)) {
              ok = false;
            }
            if (v.validator) {
              ok = v.validator(null, value, null, null, null) as boolean;
            }
            /** 其他默认认证 */
            return ok;
          })
        : true;
      return result;
    });
  }
}
